/*!
 **************************************************************
 *                                                            *  
 *   .=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-.       *  
 *    |                     ______                     |      *  
 *    |                  .-"      "-.                  |      *  
 *    |                 /            \                 |      *  
 *    |     _          |              |          _     |      *  
 *    |    ( \         |,  .-.  .-.  ,|         / )    |      *  
 *    |     > "=._     | )(__/  \__)( |     _.=" <     |      *  
 *    |    (_/"=._"=._ |/     /\     \| _.="_.="\_)    |      *  
 *    |           "=._"(_     ^^     _)"_.="           |      *  
 *    |               "=\__|IIIIII|__/="               |      *  
 *    |              _.="| \IIIIII/ |"=._              |      *  
 *    |    _     _.="_.="\          /"=._"=._     _    |      *  
 *    |   ( \_.="_.="     `--------`     "=._"=._/ )   |      *  
 *    |    > _.="                            "=._ <    |      *  
 *    |   (_/                                    \_)   |      *  
 *    |                                                |      *  
 *    '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-='      *  
 *                                                            *  
 *           LASCIATE OGNI SPERANZA, VOI CH'ENTRATE           *  
 **************************************************************   
 ******************************************************************
 *  项目名称 : proxy
 *  文件描述 :
 *  文件名称 : client.js
 *  版  本  : v1.0.0.0
 *  说  明  :  
 *  作  者  : night
 *  邮  箱  : 88962800@qq.com
 *  创建时间 : 2019:01-04 10:56 
 ******************************************************************
 Copyright © 2017-2019, All rights reserved.
 ******************************************************************
 */
import net from "net";
import path from "path";
import fs from "fs";
import Buffer from './lib/buffer';
import colors from 'colors';
let client = {
    start: function () {
        let _this = this;
        let socket =this.socket= this.createConnection();
        socket.on('data', async (bf) => {
            let buffer = new Buffer();
            buffer.push(bf);
            while (true) {
                let line = buffer.readLineSync();
                if (!line) {
                    break;
                }
                let data = JSON.parse(line.trim());
                if (data.token) {
                    this.startNewConnection(data);
                    continue;
                }
                if (data.info) {
                    console.log(colors.yellow(data.error));
                    continue
                }
                if (data.error) {
                    console.log(colors.red(data.error));
                    continue;
                }
                //console.log(data.time);
            }
        });
        socket.on('connect', () => {
            this.isConnect = true;
            let cfg = _this.getConfig()
            socket.write(JSON.stringify(cfg));
            let info = '';
            for (let i of cfg.tunnels) {
                info += `${i.proto}:${cfg.server_addr}:${i.remote_port}=====================>127.0.0.1:${i.port}\n`;
            }
            let out = colors.green(`
################################################################

${info}
################################################################
                        `);
            console.log(out);
            if(this.timer){
                clearInterval(this.timer);
               this.timer=null;
            }
            this.timer = setInterval(()=>{
                socket.write(JSON.stringify({time:new Date().getTime()}) +"\n");
            },5000);
        });
        socket.on('close', () => {
            if(this.timer){
                clearInterval(this.timer);
                this.timer=null;
            }
            // console.log("connect close");
            console.log(colors.red("server connect lost try connection....."));
            this.isConnect=false;
            this.reConnect();
        });
        socket.on('error', (e) => {
            //console.log("err happen==>", e);
        });
        socket.on('timeout',()=>{
            console.log("connect to server timeout");
            socket.destroy();
        });
        return socket;
    },
    reConnect(){
        if(this.isConnect){
            return;
        }
        this.start();

    },
    createConnection: function (cfg) {
        cfg = cfg || this.getConfig();
        let socket = net.createConnection({port: cfg.server_port, host: cfg.server_addr}, () => {
        });
        return socket;
    },
    getConfig: function () {
        try {
            if (this._config)return this._config;
            let p = path.join(__dirname, "../proxy.cfg");
            let data = fs.readFileSync(p, {encoding: 'utf8'});
            this._config = JSON.parse(data.trim());
            return this._config;
        } catch (e) {
            console.log(e);
        }
    },
    startNewConnection: function (data) {
        let socket = net.createConnection({port: data.port}, () => {
            let remote = net.createConnection({port: data.remote_port, host: this.getConfig().server_addr},()=>{
                remote.write(`${data.token}\n`);
            });
            socket.pipe(remote);
            remote.pipe(socket);
            socket.on('close', () => {
                socket = null;
                if (remote) remote.destroy();
            });
            remote.on('close', () => {
                remote = null;
                if (socket) socket.destroy();
            })
            socket.on('error', () => {
                socket.destroy();
                if (remote) remote.destroy();
            });
            remote.on('error', () => {
                remote.destroy();
                if (socket) socket.destroy();
            });
        });
    }
}
client.start();
process.on('uncaughtException', function (err) {
    //打印出错误
    console.log("uncaughtException===>", err);
});
